001 /*
002 * Copyright 2005 Stephen J. McConnell.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
013 * implied.
014 *
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package net.dpml.station.server;
020
021 import java.net.URI;
022 import java.net.URL;
023 import java.rmi.registry.Registry;
024
025 import net.dpml.cli.Option;
026 import net.dpml.cli.Group;
027 import net.dpml.cli.CommandLine;
028 import net.dpml.cli.OptionException;
029 import net.dpml.cli.commandline.Parser;
030 import net.dpml.cli.builder.ArgumentBuilder;
031 import net.dpml.cli.builder.GroupBuilder;
032 import net.dpml.cli.builder.DefaultOptionBuilder;
033 import net.dpml.cli.option.PropertyOption;
034 import net.dpml.cli.validation.URIValidator;
035 import net.dpml.cli.validation.NumberValidator;
036
037 import net.dpml.station.ApplicationRegistry;
038
039 import net.dpml.transit.Artifact;
040 import net.dpml.transit.model.TransitModel;
041
042 import net.dpml.util.Logger;
043
044 /**
045 * The RemoteStation is responsible for the establishment of
046 * callback monitors to external processes established by the
047 * station manager.
048 *
049 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
050 * @version 1.0.1
051 */
052 public class StationServerPlugin implements Runnable
053 {
054 private final Logger m_logger;
055 private final CommandLine m_line;
056 private final TransitModel m_model;
057
058 private RemoteStation m_station;
059
060 /**
061 * Creation of a new station server plugin for station commandline
062 * handling.
063 * @param logger the assigned logging channel
064 * @param model the transit model
065 * @param args the command line arguments array
066 * @exception Exception if an error occurs
067 */
068 public StationServerPlugin( Logger logger, TransitModel model, String[] args ) throws Exception
069 {
070 m_logger = logger;
071 m_model = model;
072
073 // parse the command group model
074
075 Parser parser = new Parser();
076 parser.setGroup( COMMAND_GROUP );
077 try
078 {
079 m_line = parser.parse( args );
080 }
081 catch( OptionException e )
082 {
083 final String message = "Server commandline processing error.";
084 StringBuffer buffer = new StringBuffer( message );
085 buffer.append( "\nArgument count: " + args.length );
086 for( int i=0; i<args.length; i++ )
087 {
088 buffer.append( "\n arg (" + i + "): [" + args[i] + "]" );
089 }
090 String error = buffer.toString();
091 throw new Exception( error, e );
092 }
093 }
094
095 /**
096 * Start the thread.
097 */
098 public void run()
099 {
100 try
101 {
102 int port = getPortValue( m_line, Registry.REGISTRY_PORT );
103 URI uri = (URI) m_line.getValue( URI_OPTION, null );
104 if( null == uri )
105 {
106 URL url = ApplicationRegistry.DEFAULT_STORAGE_URI.toURL();
107 m_logger.info( "starting station on port: " + port );
108 m_station = new RemoteStation( m_logger, m_model, port, url );
109 Thread.currentThread().setContextClassLoader( ApplicationRegistry.class.getClassLoader() );
110 setShutdownHook( m_station );
111 }
112 else
113 {
114 if( Artifact.isRecognized( uri ) )
115 {
116 URL url = Artifact.createArtifact( uri ).toURL();
117 m_logger.info(
118 "starting station on port: "
119 + port
120 + " with registry "
121 + url );
122 m_station = new RemoteStation( m_logger, m_model, port, url );
123 }
124 else
125 {
126 URL url = uri.toURL();
127 m_logger.info(
128 "starting station on port: "
129 + port
130 + " with registry "
131 + url );
132 m_station = new RemoteStation( m_logger, m_model, port, url );
133 }
134 }
135 }
136 catch( Exception e )
137 {
138 final String error =
139 "Station startup failure.";
140 m_logger.error( error, e );
141 }
142 }
143
144 private int getPortValue( CommandLine line, int defaultPort )
145 {
146 if( line.hasOption( PORT_OPTION ) )
147 {
148 Number number = (Number) line.getValue( PORT_OPTION, null );
149 return number.intValue();
150 }
151 else
152 {
153 return defaultPort;
154 }
155 }
156
157 private URI getRegistryURI( CommandLine line, URI uri )
158 {
159 if( line.hasOption( URI_OPTION ) )
160 {
161 return (URI) line.getValue( URI_OPTION, null );
162 }
163 else
164 {
165 return uri;
166 }
167 }
168
169 /**
170 * Create a shutdown hook that will trigger shutdown of the station.
171 * @param station the station
172 */
173 public static void setShutdownHook( final RemoteStation station )
174 {
175 Runtime.getRuntime().addShutdownHook( new ShutdownHandler( station ) );
176 }
177
178 private static final DefaultOptionBuilder OPTION_BUILDER = new DefaultOptionBuilder();
179 private static final ArgumentBuilder ARGUMENT_BUILDER = new ArgumentBuilder();
180 private static final GroupBuilder GROUP_BUILDER = new GroupBuilder();
181
182 private static final PropertyOption PROPERTY_OPTION = new PropertyOption();
183 private static final NumberValidator NUMBER_VALIDATOR = NumberValidator.getIntegerInstance();
184
185 private static final Option PORT_OPTION =
186 ARGUMENT_BUILDER
187 .withDescription( "Port number." )
188 .withName( "port" )
189 .withMinimum( 0 )
190 .withMaximum( 1 )
191 .withValidator( NUMBER_VALIDATOR )
192 .create();
193
194 private static final Option URI_OPTION =
195 OPTION_BUILDER
196 .withShortName( "registry" )
197 .withDescription( "Application registry store." )
198 .withRequired( false )
199 .withArgument(
200 ARGUMENT_BUILDER
201 .withDescription( "Local or remote artifact reference." )
202 .withName( "artifact" )
203 .withMinimum( 1 )
204 .withMaximum( 1 )
205 .withValidator( new URIValidator() )
206 .create() )
207 .create();
208
209 private static final Group COMMAND_GROUP =
210 GROUP_BUILDER
211 .withName( "options" )
212 .withOption( PORT_OPTION )
213 .withOption( URI_OPTION )
214 .withOption( PROPERTY_OPTION )
215 .create();
216
217 /**
218 * Shutdown handler implementation.
219 */
220 private static class ShutdownHandler extends Thread
221 {
222 private final RemoteStation m_station;
223
224 /**
225 * Creation of a new shutdown handler.
226 * @param station the station to shutdown
227 */
228 ShutdownHandler( final RemoteStation station )
229 {
230 m_station = station;
231 }
232
233 public void run()
234 {
235 m_station.shutdown();
236 }
237 }
238
239 }